package com.highspeed.bdk.gateway.netty.analyze.client;

import com.highspeed.bdk.gateway.entity.Constants;
import com.highspeed.bdk.gateway.entity.LuckHeader;
import com.highspeed.bdk.gateway.entity.LuckMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.HashMap;
import java.util.Map;

/**
 * netty通道工具类
 */
public class TcpClientUtils {

    //连接IP
    public static String HOST = "192.168.0.185";
    //连接端口
    public static int PORT = 8001;
    private static int totalCount = 0;
    public static Bootstrap bootstrap = getBootstrap();
    public static Channel channel = getChannel(HOST, PORT);

    /**
     * 初始化Bootstrap
     */
    public static final Bootstrap getBootstrap() {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(group).channel(NioSocketChannel.class);
        b.handler(new NettyClientInitializer());
        b.option(ChannelOption.SO_KEEPALIVE, true);
        return b;
    }

    /**
     * 获取连接通道
     * @param host
     * @param port
     * @return
     */
    public static final Channel getChannel(String host, int port) {
        Channel channel = null;
        try {
            channel = bootstrap.connect(host, port).sync().channel();
        } catch (Exception e) {
//            System.out.println("连接Server(IP{},PORT{})失败");
            return null;
        }
        return channel;
    }

    /**
     * 发送消息
     * @param key 操作号
     * @param content 内容参数
     * @throws Exception
     */
    public static void sendMsg(Short key,byte[] content) throws Exception {

        LuckHeader luckHeader = new LuckHeader((char) 0xffff, (short)totalCount, key, (char) 1, content.length);
        LuckMessage message = new LuckMessage(luckHeader, content);
        if (channel != null) {
            System.out.print(key);
            totalCount++;
            channel.writeAndFlush(message).sync();
        }
    }

    /**
     * 初始化
     * @throws Exception
     */
    public static void initFbData() throws Exception {
       sendMsg(Constants.INIT_FB_DATA,null);

    }

    /**
     * 物理链路统计信息
     * @throws Exception
     */
    public static void phyLinkStatic() throws Exception {
        sendMsg(Constants.PHYLINK_STATICS,null);

    }

    /**
     * 查询芯片节点信息
     * @param 芯片节点Id
     * @throws Exception
     */
    public static void deviceNodeFbData(Short param) throws Exception {

        sendMsg(Constants.DEVICE_NODE_FB_DATA,shortToByteArray(param));

    }

    /**
     * 从Flash获取xml
     * @throws Exception
     */
    public static void xmlFromFlash() throws Exception {
        sendMsg(Constants.XML_FROM_FLASH,null);

    }

    public static void main(String[] args) throws Exception {
        try {
            long t0 = System.nanoTime();
            Map<Short, String> map = new HashMap<>();
//            map.put((short) 0x01, "查询板卡总信息");
            map.put((short) 0x02, "查询初始化后网络状态");
//            map.put((short) 0x03, "11");
//            map.put((short) 0x05, "查询物理端口信息");
//            map.put((short) 0x07, "查询板物理链路信息");
//            map.put((short) 0x09, "查询逻辑链路信息");
//            map.put((short) 0x0B, "查询逻辑端口信息");
//            map.put((short) 0x0D, "查询物理链路上的逻辑链路");
//            map.put((short) 0x0E, "查询一条逻辑链路对应的路录表");
//            map.put((short)0x0f, "查询逻辑链路下物理链路");
//            map.put((short) 0x11, "查询板卡主备信息");
//            map.put((short) 0x12, "查询所有的逻辑链路对应的物理链路");
//            map.put((short) 0x13, "查询所有逻辑链路");
//            map.put((short) 0x14, "查询所有逻辑链路的路由表");
//            map.put((short) 0x15, "查询多播组");
//            map.put((short) 0x17, "查询一个多播");
//            map.put((short) 0x19, "查询APP（组件信息）");
//            map.put((short) 0x18, "通过ICD配置和重构");
//            map.put((short) 0x20, "读寄存器器");
//            map.put((short) 0x21, "写寄存器器");
//            map.put((short) 0x24, "查询一条逻辑链路上的统计信息");
//            map.put((short) 0x27, "查询一条物理链路统计信息");
//            map.put((short) 0x28, "查询所有物理链路统计信息");
//            map.put((short) 0x29, "下发烧写预置表命令（下发组件关联表）");
//            map.put((short) 0x30, "下发烧写部署表命令");
//            map.put((short) 0x31, "下发从flash中读出预置表命令");
//            map.put((short) 0x32, "下发从flash中读出部署表命令");
//            map.put((short) 0x33, "下发配置块数据单播逻辑链路");
//            map.put((short) 0x34, "下发配置块数据多播逻辑链路");
//            map.put((short) 0x35, "下发配置消息逻辑链路");
//            map.put((short) 0x83, "下发烧写网络拓扑");
//            map.put((short) 0x84, "下发从flash中读出XML文件命令");
//            map.put((short) 0x91, "查询日志");
//            map.put((short) 0xA1, "发送连接请求");
//            map.put((short) 0xA3, "发送退出请求");
//            map.put((short) 0xA4, "查询告警信息");
//            map.put((short) 0x71, "发送命令行命令");
            for (Short key :
                    map.keySet()) {
                /**
                 * 第一个操纵号，第二个添加参数ID
                 */
                TcpClientUtils.sendMsg(key,map.get(key).getBytes());
            }


            long t1 = System.nanoTime();
//            System.out.println("time used:{}");
        } catch (Exception e) {
            System.out.println("main err:" + e);
        }
    }


    public static byte[] shortToByteArray(short s) {
        byte[] targets = new byte[2];
        for (int i = 0; i < 2; i++) {
            int offset = (targets.length - 1 - i) * 8;
            targets[i] = (byte) ((s >>> offset) & 0xff);
        }
        return targets;
    }
}